package com.company;
//https://www.cnblogs.com/myseries/p/10918819.html

/*1. interrupt()说明
2. 终止线程的方式
  2.1 终止处于“阻塞状态”的线程
  2.2 终止处于“运行状态”的线程
3. 终止线程的示例
4. interrupted() 和 isInterrupted()的区别*/

/*interrupt()的作用是中断本线程。
本线程中断自己是被允许的；其它线程调用本线程的interrupt()方法时，会通过checkAccess()检查权限。
这有可能抛出SecurityException异常。
如果本线程是处于阻塞状态：调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态，
或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。
若线程在阻塞状态时，调用了它的interrupt()方法，那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。
例如，线程通过wait()进入阻塞状态，此时通过interrupt()中断该线程；
调用interrupt()会立即将线程的中断标记设为“true”，但是由于线程处于阻塞状态，
所以该“中断标记”会立即被清除为“false”，同时，会产生一个InterruptedException的异常。
如果线程被阻塞在一个Selector选择器中，那么通过interrupt()中断它时；
线程的中断标记会被设置为true，并且它会立即从选择操作中返回。
如果不属于前面所说的情况，那么通过interrupt()中断线程时，它的中断标记会被设置为“true”。
中断一个“已终止的线程”不会产生任何操作。*/


import java.util.Scanner;

public class C07MultiThreadinginterrupt {

//    public static void main(String[] arg) throws InterruptedException {
//
//        MyThread myThread = new MyThread();
//        myThread.start();
//        Thread.sleep(100);
//        myThread.interrupt(); //作用是：在线程阻塞时抛出一个中断信号，这样线程就得以退出阻塞的状态
//        System.out.println("线程是否被中断：" + myThread.isInterrupted());//true
//    }
//
//    public static class MyThread extends Thread {
//
//        private Object lock=new Object();
//        @Override
//        public void run() {
//            System.out.println("线程启动了");
//////              2.1 终止处于“阻塞状态”的线程
////            try{
////                 Thread.sleep(1000 * 100);
//////                synchronized (lock){
//////                    try {
//////                        lock.wait(10000);
//////                    } catch (InterruptedException e) {
//////                        System.out.println("线程结束了wait（中断）");
//////                    }
//////                }
////            }catch(InterruptedException ex){
////                System.out.println("线程结束了sleep（中断）");
////            }
////             2.2 终止处于“运行状态”的线程
//            while (!isInterrupted()) {
//                System.out.println(isInterrupted());//调用 interrupt 之后为true
//            }
//            System.out.println("线程结束了");
//        }
//    }

//   被volatile修饰的共享变量，就具有了以下两点特性：
//            1.保证了不同线程对该变量操作的内存可见性;
//            2.禁止指令重排序
//    https://www.techug.com/post/java-volatile-keyword.html


    static volatile Integer count = 0;
    static volatile boolean flag = false;

    public static void main(String[] args) throws InterruptedException {

        MyThread myThread = new MyThread();

        Scanner scanner = new Scanner(System.in);
        System.out.println("输入1重头开始计数，输入2中止计数，输入3继续计数\n");
        while (scanner.hasNext()) {
            String text = scanner.next();
            System.out.println("你输入了：" + text + "\n");
            //输入1开始计数
            if ("1".equals(text)) {
                if (myThread.isAlive()){
                    System.out.println("------------------子线程中断操作开始------------------");
                    //注意，此方法不会中断一个正在运行的线程，它的作用是：
                    // 在线程受到阻塞时抛出一个中断信号，这样线程就得以退出阻塞的状态
//                     我们的方案是 子线程：中捕捉到信号（退出阻塞的状态），然后break强制退出循环，然后就可以自然的 结束子线程
                    myThread.interrupt();
                    Thread.sleep(1000);
                    System.out.println("------------------子线程中断操作结束------------------"+ myThread.isInterrupted());

                    System.out.println("重头开始计数\n");
                    flag=true;
                    count = 0;
                    myThread = new MyThread();
                    myThread.start();

                }else{
                    System.out.println("重头开始计数\n");
                    flag=true;
                    count = 0;
                    myThread = new MyThread();
                    myThread.start();
                }
            } else if ("2".equals(text)) { //输入2计数中止
                if (myThread.isAlive()){

                    System.out.println("------------------子线程中断操作开始------------------");
                    //注意，此方法不会中断一个正在运行的线程，它的作用是：
                    // 在线程受到阻塞时抛出一个中断信号，这样线程就得以退出阻塞的状态
//                     我们的方案是 子线程：中捕捉到信号（退出阻塞的状态），然后break强制退出循环，然后就可以自然的 结束子线程
                    myThread.interrupt();
                    Thread.sleep(1000);
                    System.out.println("------------------子线程中断操作结束------------------"+ myThread.isInterrupted());
                    System.out.println("中止计数\n");

                }else{
                    flag=false;
                    System.out.println("中止计数\n");
                }

            } else if ("3".equals(text)) { //输入3继续计数
                if (!myThread.isAlive()){
                    flag=true;
                    myThread = new MyThread();
                    myThread.start();
                }
                System.out.println("继续计数\n");

            } else {    //输入其它数字 结束子线程  结束主线程

                if (myThread.isAlive()){

                    System.out.println("------------------子线程中断操作开始------------------");
                    //注意，此方法不会中断一个正在运行的线程，它的作用是：
                    // 在线程受到阻塞时抛出一个中断信号，这样线程就得以退出阻塞的状态
//                     我们的方案是 子线程：中捕捉到信号（退出阻塞的状态），然后break强制退出循环，然后就可以自然的 结束子线程
                    myThread.interrupt();
                    Thread.sleep(1000);
                    System.out.println("------------------子线程中断操作结束------------------"+ myThread.isInterrupted());

                }else{
                    flag=false;
                }
                break;
            }
        }
        scanner.close();
        System.out.println("------------------主线程结束------------------");
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            while(!isInterrupted()){
//            while(true){
                try {
                    this.sleep(2000);
                    if (flag){
                        count = count + 1;
                        System.out.println(count);
                    }
                } catch (InterruptedException e) {
                    System.out.println("------------------子线程中断------------------"+this.isInterrupted());
                    break; // 这里 非常重要，当捕捉到中断命令是，强制退出循环，继续执行下面的代码直至子线程结束
                }
            }
            flag=false;
            System.out.println("------------------子线程结束------------------");
        }

    }


//    public static void main(String[] args) throws InterruptedException {
//
//        MyThread myThread=new MyThread();
//        myThread.start();
//        Thread.sleep(1000);
//        myThread.interrupt();
//
//        System.out.println("------------------子线程中断------------------"+myThread.isInterrupted());
//        System.out.println("------------------子线程中断------------------"+myThread.isInterrupted());
//
////        interrupt()是将线程的中断标记设置为true，但不会停止线程。
////        在中断状态下如果线程处于阻塞状态（即调用了sleep(),wait(),join()方法）
////        就会产生一个InterruptedException，并且由于线程处于阻塞状态，所以该中断标记立即清除为false
////        interrupted()是测试当前线程是否处于中断状态，是返回true，并且调用后会立即将该中断标记清除为false
////        原文链接：https://blog.csdn.net/Beer_xiaocai/article/details/102015171
//        Thread.currentThread().interrupt();
//        System.out.println("------------------主线程中断------------------"+Thread.interrupted());
//        System.out.println("------------------主线程中断------------------"+Thread.interrupted());
//        System.out.println("------------------主线程中断------------------"+Thread.interrupted());
//        System.out.println("------------------主线程中断------------------"+Thread.interrupted());
//    }
//
//    public static class MyThread extends Thread {
//        @Override
//        public void run() {
//
//            while (true) {
//                if (!this.isInterrupted()) {
//                    System.out.println("------------------子线程运行------------------");
//                }
//            }
//        }
//    }

}
